﻿#include "CubMapScene.h"

#include "Camera.h"
#include "CubeMapMaterial.h"
#include "Debuger.h"
#include "Render.h"
#include "MaterialSrc/CubeMaterial.h"
#include "MaterialSrc/EnvironmentMappingMaterial.h"


static float GCubeVertices[] = {
	// Back face
	-0.5f, -0.5f, -0.5f,  0.0f, 0.0f, // Bottom-left
	0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right
	0.5f, -0.5f, -0.5f,  1.0f, 0.0f, // bottom-right         
	0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right
	-0.5f, -0.5f, -0.5f,  0.0f, 0.0f, // bottom-left
	-0.5f,  0.5f, -0.5f,  0.0f, 1.0f, // top-left
									  // Front face
	-0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-left
	0.5f, -0.5f,  0.5f,  1.0f, 0.0f, // bottom-right
	0.5f,  0.5f,  0.5f,  1.0f, 1.0f, // top-right
	0.5f,  0.5f,  0.5f,  1.0f, 1.0f, // top-right
	-0.5f,  0.5f,  0.5f,  0.0f, 1.0f, // top-left
	-0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-left
																		// Left face
	-0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-right
	-0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-left
	-0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-left
	-0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-left
	-0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-right
	-0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-right
	// Right face
	0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-left
	0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-right
	0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right         
	0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-right
	0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-left
	0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-left     
	// Bottom face
	-0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // top-right
	0.5f, -0.5f, -0.5f,  1.0f, 1.0f, // top-left
	0.5f, -0.5f,  0.5f,  1.0f, 0.0f, // bottom-left
	0.5f, -0.5f,  0.5f,  1.0f, 0.0f, // bottom-left
	-0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-right
	-0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // top-right

	-0.5f,  0.5f, -0.5f,  0.0f, 1.0f, // top-left
	0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // bottom-right
	0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right     
	0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // bottom-right
	-0.5f,  0.5f, -0.5f,  0.0f, 1.0f, // top-left
	-0.5f,  0.5f,  0.5f,  0.0f, 0.0f  // bottom-left        
};

float GVerticesPosNorma[] = {
	-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	-0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,

	-0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
	0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
	0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
	0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
	-0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
	-0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,

	-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
	-0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
	-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
	-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
	-0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
	-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,

	0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
	0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
	0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
	0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
	0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
	0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,

	-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
	0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
	0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
	0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
	-0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
	-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,

	-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
	0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
	0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
	0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
	-0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
	-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f
};

void FCubMapScene::Init(FRender* InRender)
{
	FScence::Init(InRender);

	Camera = CreateDefaultCamera();

	const auto SkyBoxMaterial = std::make_shared<FCubeMapMaterial>();
	SkyBox = std::make_shared<FMesh>();
	std::vector<FVertexInfo> BoxVertex;

	for (int32_t Index = 0; Index < 180;)
	{
		BoxVertex.push_back(
			FVertexInfo
			{
				glm::vec3(GCubeVertices[Index + 0], GCubeVertices[Index + 1],GCubeVertices[Index + 2]),
				glm::vec3(),
				glm::vec2(GCubeVertices[Index + 3], GCubeVertices[Index + 4])
			}
		);
		Index += 5;
	}

	std::vector<FVertexInfo> BoxPosNormalVertex;
	for (int32_t Index = 0; Index < 216;)
	{
		BoxPosNormalVertex.push_back(
			FVertexInfo
			{
				glm::vec3(GVerticesPosNorma[Index + 0], GVerticesPosNorma[Index + 1],GVerticesPosNorma[Index + 2]),
				glm::vec3(GVerticesPosNorma[Index + 3], GVerticesPosNorma[Index + 4], GVerticesPosNorma[Index + 5]),
				glm::vec2()
			}
		);
		Index += 6;
	}


	SkyBox->Init(BoxVertex, SkyBoxMaterial);

	Box = std::make_shared<FMesh>();
	const auto CubeMaterial = std::make_shared<FCubeMaterial>();
	Box->Init(BoxVertex, CubeMaterial);

	BoxEnvMap = std::make_shared<FMesh>();
	BoxEnvMapMaterial = std::make_shared<FEnvironmentMappingMaterial>();
	BoxEnvMap->Init(BoxPosNormalVertex, BoxEnvMapMaterial);
	BoxEnvMap->OnSetShaderData = [this](const std::shared_ptr<FShaderProgram>& Shader)
	{
		Shader->SetVec3("cameraPos", Camera->GetPosition());
	};

}

void FCubMapScene::Destory()
{
	FScence::Destory();
}

void FCubMapScene::Draw(float DateTime)
{
	FScence::Draw(DateTime);

	auto Projection = glm::mat4(1.f);
	Projection = glm::perspective(glm::radians(Camera->GetFOV()), Render->GetAspect(), 0.1f, 100.0f);

	FDrawArg DrawArg;
	DrawArg.DateTime = DateTime;
	DrawArg.LightArray = { };
	DrawArg.ViewMat = Camera->GetViewMat();
	DrawArg.ViewPos = Camera->GetPosition();
	DrawArg.ProjectionMat = Projection;

	DebugInfor("ViewPos %f,%f,%f",DrawArg.ViewPos.x, DrawArg.ViewPos.y, DrawArg.ViewPos.z);


	glm::mat4 ModelMat = glm::mat4(1.f);
	Box->SetTransform(ModelMat);
	Box->Draw(DrawArg);

	ModelMat = glm::mat4(1.f);
	ModelMat = glm::translate(ModelMat, glm::vec3(2.f, 0.f, 0.f));
	BoxEnvMap->SetTransform(ModelMat);
	BoxEnvMapMaterial->SetEnvType(FEnvironmentMappingMaterial::Reflact);
	BoxEnvMap->Draw(DrawArg);


	ModelMat = glm::mat4(1.f);
	ModelMat = glm::translate(ModelMat, glm::vec3(-2.f, 0.f, 0.f));
	BoxEnvMap->SetTransform(ModelMat);
	BoxEnvMapMaterial->SetEnvType(FEnvironmentMappingMaterial::Refract);
	BoxEnvMap->Draw(DrawArg);

	DrawArg.ViewMat = glm::mat4(glm::mat3(Camera->GetViewMat()));
	glDepthFunc(GL_LEQUAL);
	SkyBox->Draw(DrawArg);
	glDepthFunc(GL_LESS);

}
